package com.tjh.springbootapi.webSocket;

import com.tjh.springbootapi.webSocket.utils.StrUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Create by koala on 2022-08-14
 */
@Slf4j
public class ChannelSupervise {

    private static ChannelGroup GlobalGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    public static ConcurrentMap<String, ChannelId> ChannelMap = new ConcurrentHashMap<>();
    public static ConcurrentMap<String, ChannelId> businessChannelMap = new ConcurrentHashMap<>();
    public static ConcurrentMap<String, List<Channel>> multiBusinessChannelMap = new ConcurrentHashMap<>();
    /**
     * 存储socket的授权key，一旦验证并启动通道，则移除改key
     * @date : 2022/4/18 by 61775
     **/
    public static ConcurrentMap<String, String> socketKeyMap = new ConcurrentHashMap<>();

    public static void cacheChannel(Channel channel) {
        GlobalGroup.add(channel);
    }

    public static void removeCacheChannel(Channel channel) {
        GlobalGroup.remove(channel);
    }

    public static void addChannel(Channel channel) {
        ChannelId channelId = ChannelMap.get(channel.id().asShortText());
        if (Objects.nonNull(channelId)) {
            Channel oldChannel = GlobalGroup.find(channelId);
            if (Objects.nonNull(oldChannel)) {
                GlobalGroup.remove(channel);
            }
            ChannelMap.remove(channel.id().asShortText());
        }
        ChannelMap.put(channel.id().asShortText(), channel.id());
    }

    public static void removeChannel(Channel channel) {
        GlobalGroup.remove(channel);
        ChannelMap.remove(channel.id().asShortText());
        String businessKey = findBusinessKey(channel.id());
        if (StrUtils.isNotBlank(businessKey)) {
//            V2UpdateRowCell.archivesRowDataMap.remove(gridKey);
            businessChannelMap.remove(businessKey);
        }
    }

    public static Channel findChannel(String id) {
        //channel
        ChannelId channelId = ChannelMap.get(id);
        if (Objects.isNull(channelId)) {
            for (String key : businessChannelMap.keySet()) {
                channelId = businessChannelMap.get(key);
                break;
            }
        }
        if (Objects.nonNull(channelId)) {
            Channel channel = GlobalGroup.find(channelId);
            if (Objects.nonNull(channel)) {
                return channel;
            }
        }
        return null;
    }

    public static Channel findChannel(ChannelId channelId) {
        if (Objects.nonNull(channelId)) {
            Channel channel = GlobalGroup.find(channelId);
            if (Objects.nonNull(channel)) {
                return channel;
            }
        }
        return null;
    }

    public static String findBusinessKey(ChannelId channelId) {
        for (String key : businessChannelMap.keySet()) {
            ChannelId curChannelId = businessChannelMap.get(key);
            if (channelId.equals(curChannelId)) {
                return key;
            }
        }
        return null;
    }

    public static void send2All(TextWebSocketFrame tws) {
        GlobalGroup.writeAndFlush(tws);
    }

    public static void send2Channel(String channelId, String contentText) {
        Channel channel = findChannel(channelId);
        if (Objects.nonNull(channel)) {
            channel.writeAndFlush(new TextWebSocketFrame(contentText));
        }
    }

    public static void send2Channels(List<Channel> channelList, String contentText) {
        for (Channel channel : channelList) {
            if(channel.isActive()){
                channel.writeAndFlush(new TextWebSocketFrame(contentText));
            }else {
                removeChannel(channel);
            }
        }
    }

    public static void send2Channel(Channel channel, String contentText) {
        if (Objects.nonNull(channel)) {
            channel.writeAndFlush(new TextWebSocketFrame(contentText));
        }
    }
}